package com.ruoyi.quartz.task;

import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.MultipartFileDto2;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.JacksonUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.http.HttpUtils2;
import com.ruoyi.quartz.domain.Response;
import com.ruoyi.quartz.domain.ResponseArray;
import com.ruoyi.quartz.service.ISysJobLogService;
import com.ruoyi.swla2.domain.*;
import com.ruoyi.swla2.service.*;
import com.ruoyi.swla2.util.DTSUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.stream.Collectors;

import static javax.swing.text.DefaultStyledDocument.ElementSpec.ContentType;

/**
 * @author TsingYu
 * @version 1.0
 * 迪泰森定时任务
 * @date 2025/6/25 13:21
 *
 */

@Component("dtsTask")
public class DtsTask {

    private static final Logger log = LoggerFactory.getLogger(DtsTask.class);


    @Autowired
    private IDeviceLedgerService deviceLedgerService;

    @Autowired
    private IFileVideoService fileVideoService;

    @Autowired
    private IVideoSpectrumService videoSpectrumService;

    @Autowired
    private IDeviceService deviceService;

    @Autowired
    private ITaskManagementService taskManagementService  ;



    /**
     * 迪泰森接口默认基础Url
     */
    private final static String DEFAULT_BASE_URL = "http://39.105.151.103:8080/wam/api/";

    /**
     * 设备信息接口Url
     */
    private final static String DEVICE_INFO_URL = "v1/getDeviceInfo";

    /**
     * 音频文件列表接口
     */
    private final static String WAV_FILE_URL = "v1/getWavFileList";

    /**
     * 音频文件下载接口
     */
    private final static String DOWNLOAD_WAV_FILE_URL = "v1/downloadWavFile";

    /**
     * 每日设备预警值接口
     */
    private final static String DAILY_ALARM_URL = "v1/getDailyAlarmData";

    /**
     * 音频文件频谱图数据接口
     */
    private final static String WAV_FILE_SPECTRUM_URL = "v1/getWavFileSpectrumData";

    /**
     * 音频文件状态接口
     */
    private final static String Status_INFO_URL = "v1/getStatus";

    /**
     * 音频文件状态接口
     */
    private final static String DEFAULT_USER_NAME = "admin";
    private final static String FILE_NAME = "fileName";
    private final static String REPORT_DAY = "day";

    /**
     *
     */
    private final static String TASK_STATUS_WARNING_CN = "预警";
    private final static String TASK_STATUS_WARNING_VALUE = "3";


    private final static String TASK_STATUS_SUSPECTED_CN = "疑似";
    private final static String TASK_STATUS_SUSPECTED_VALUE = "2";



    private <T> List<T> getList(String urlVar, Class<T> clazz, Map<String, String> params) {
        List<T>  list = new ArrayList<>();
        String url = DEFAULT_BASE_URL + urlVar;
        HttpUtils2 httpUtils = new HttpUtils2();
        String resDeviceInfo = null;
        try {
            resDeviceInfo = httpUtils.get(url, params);
            log.info("同步测漏仪数据-url:{},参数：{}，返回报文：{}", urlVar,
                    new ObjectMapper().writeValueAsString(params), resDeviceInfo);
        } catch (IOException e) {
            log.error("同步测漏仪数据-获取设备信息出错", e);
            throw new RuntimeException(e);
        }
        if (StringUtils.isBlank(resDeviceInfo)) {
            log.info("设备信息接口无响应");
            return list;
        }
        Response<T> responseDeviceInfo = null;
        try {
            responseDeviceInfo = JacksonUtils.jsonToObject(
                    resDeviceInfo, Response.class, clazz);
        } catch (Exception e) {
            log.error("数据解析出错，返回信息：{}", e.getMessage());
            throw new RuntimeException(e);
        }
        if (!responseDeviceInfo.getCode().equals(
                Response.ResponseCode.OK.getCode())) {
            log.error("同步测漏仪数据出错，返回信息：{}", responseDeviceInfo.getMessage());
            return list;
        }

         return responseDeviceInfo.getData();
    }


    private JSONArray getDataString(String urlVar, Map<String, String> params) {
        String url = DEFAULT_BASE_URL + urlVar;
        HttpUtils2 httpUtils = new HttpUtils2();
        String resDeviceInfo = null;
        try {
            resDeviceInfo = httpUtils.get(url, params);
            log.info("同步测漏仪数据-url:{},参数：{}，返回报文：{}", urlVar,
                    new ObjectMapper().writeValueAsString(params), resDeviceInfo);
        } catch (IOException e) {
            log.error("同步测漏仪数据-获取设备信息出错", e);
            throw new RuntimeException(e);
        }
        if (StringUtils.isBlank(resDeviceInfo)) {
            log.info("设备信息接口无响应");
            return null;
        }
        ResponseArray responseDeviceInfo = null;
        try {
            responseDeviceInfo = JacksonUtils.jsonToObject(
                    resDeviceInfo, ResponseArray.class);
        } catch (Exception e) {
            log.error("数据解析出错，返回信息：{}", e.getMessage());
            throw new RuntimeException(e);
        }
        if (!responseDeviceInfo.getCode().equals(
                Response.ResponseCode.OK.getCode())) {
            log.error("同步测漏仪数据出错，返回信息：{}", responseDeviceInfo.getMessage());
            return null;
        }

        return responseDeviceInfo.getData();
    }




    private MultipartFile getMultipartFile(String urlVar,  Map<String, String> params) {
        MultipartFile multipartFile = null;
        String url = DEFAULT_BASE_URL + urlVar;
        HttpUtils2 httpUtils = new HttpUtils2();
        String resDeviceInfo = null;
        try {
            resDeviceInfo = httpUtils.get(url, params);
        } catch (IOException e) {
            log.error("同步测漏仪数据-音频文件下载出错", e);
            throw new RuntimeException(e);
        }
        if (StringUtils.isBlank(resDeviceInfo)) {
            log.info("音频文件下载接口无响应");
            return multipartFile;
        }

        try {
            multipartFile = convert(resDeviceInfo, params.get(FILE_NAME),"Audio/wav");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return multipartFile;
    }


    /**
     * {
     *     "requestId": "123134b6-51c7-4e80-84b0-21bb562cf863",
     *     "httpCode": "200",
     *     "code": "Success",
     *     "message": "Success",
     *     "totalCount": 1,
     *     "data": [
     *         {
     *             "deviceNum": "test001",
     *             "status": "off-line",
     *             "longitude": "安装经度",
     *             "latitude": "安装纬度",
     *             "region": null,
     *             "installTime": "2025-06-25 00:00:00",
     *             "installPosition": "安装位置"
     *         }
     *     ]
     * }
     */



    /**
     * @Description: 同步测漏仪数据（设备台账，音频文件，音频文件频谱图）
     * @date: 2025/6/25 11:16
     * @author: jipf
     */
    public void syncDb() throws Exception {
        System.out.println("================start  dts============================");
        //TODO   拉取所有的设备信息   将日期填充进 表示为今天的设备信息 入台账表
        Date currentDate = DateUtils.getNowDate();
        QueryWrapper<DeviceLedger>  deviceLedgerQueryWrapper = new QueryWrapper<>();
        deviceLedgerQueryWrapper.lambda().eq(DeviceLedger::getReportDay, DateUtils.dateTimeNow("yyyy-MM-dd"));
        List<DeviceLedger> deviceLedgers = deviceLedgerService.list(deviceLedgerQueryWrapper);
        if(deviceLedgers.size() >0 ){
            return;
        }

        Map<String, String> params = null;
        // params = DTSUtils.getSignature();
        // params.put("deviceNum", "24120838");
        //TODO  测试写死点
        List<DeviceLedger> listDeviceLedger = getList(DEVICE_INFO_URL, DeviceLedger.class, DTSUtils.getSignature());
        // List<DeviceLedger> listDeviceLedger = getList(DEVICE_INFO_URL, DeviceLedger.class, params);
        if(CollectionUtils.isEmpty(listDeviceLedger)){
            return;
        }

        listDeviceLedger.stream().forEach(deviceLedger -> {
            deviceLedger.setReportDay(currentDate);
            deviceLedger.setCreateBy(DEFAULT_USER_NAME);
            deviceLedger.setUpdateBy(DEFAULT_USER_NAME);
            deviceLedger.setCreateTime(currentDate);
            deviceLedger.setUpdateTime(currentDate);
        });
        boolean flagLedger = deviceLedgerService.saveBatch(listDeviceLedger);
        if (!flagLedger) {
            log.error("同步测漏仪数据-设备台账保存失败");
            return;
        }
        //TODO  测试ing  设备表  老更新 新插入
        List<Device> listDevice = deviceService.list();
        List<String> deviceNumListExist = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(listDevice)){
            for (Device device : listDevice){
                listDeviceLedger.stream().forEach(e->{
                    if(e.getDeviceNum().equals(device.getDeviceNum())){
                        device.setUpdateTime(new Date());
                        device.setUpdateBy(DEFAULT_USER_NAME);
                        device.setInstallTime(e.getInstallTime());
                        device.setInstallPosition(e.getInstallPosition());
                        deviceService.updateById(device);
                    }
                });
            }
            deviceNumListExist = listDevice.stream().map(Device::getDeviceNum)
                    .collect(Collectors.toList());
        }
        //新插入
        List<String> finalDeviceNumListExist = deviceNumListExist;
        listDeviceLedger.stream().filter(e->!finalDeviceNumListExist.contains(e.getDeviceNum())).forEach
                (e->{
                    Device device = new Device();
                    device.setDeviceNum(e.getDeviceNum());
                    device.setInstallTime(e.getInstallTime());
                    device.setInstallPosition(e.getInstallPosition());
                    device.setCreateTime(new Date());
                    device.setCreateBy(DEFAULT_USER_NAME);
                    device.setUpdateTime(new Date());
                    device.setUpdateBy(DEFAULT_USER_NAME);
                    deviceService.save(device);
                });


        //查询出当天的所有音频文件信息   预警值信息
        // TODO  测试写死点
        String currentDateStr = new SimpleDateFormat("yyyy-MM-dd").format(currentDate);
        // String currentDateStr = "2025-07-01";

        //根据设备的设备编号匹配 【音频文件 | 匹配预警值】  入音频文件表
        params =  DTSUtils.getSignature();
        params.put(REPORT_DAY, currentDateStr);
        List<FileVideo> listFileVideo = getList(WAV_FILE_URL, FileVideo.class, params);
        if(CollectionUtils.isEmpty(listFileVideo)){
            return;
        }

        params =  DTSUtils.getSignature();
        params.put(REPORT_DAY, currentDateStr);
        List<DailyAlarm> listDailyAlarm = getList(DAILY_ALARM_URL, DailyAlarm.class, params);


        listFileVideo.stream().forEach(fileVideo -> {
            fileVideo.setReportDay(currentDate);
            fileVideo.setCreateBy(DEFAULT_USER_NAME);
            fileVideo.setUpdateBy(DEFAULT_USER_NAME);
            fileVideo.setCreateTime(currentDate);
            fileVideo.setUpdateTime(currentDate);
            String targetDeviceNum = fileVideo.getDeviceNum(); //
            listDeviceLedger.stream().filter(e->targetDeviceNum.equals(e.getDeviceNum()))
                    .findFirst()
                    .ifPresent(deviceLedger -> {
                fileVideo.setLedgerId(deviceLedger.getId());
            });

            if(CollectionUtils.isNotEmpty(listDailyAlarm)){
                listDailyAlarm.stream().filter(e->targetDeviceNum.equals(e.getDeviceNum()))
                        .findFirst()
                        .ifPresent(deviceLedger -> {
                            fileVideo.setDbValue(String.valueOf(deviceLedger.getValue()));
                            fileVideo.setNoiseReference(String.valueOf(deviceLedger.getNoiseReference()));
                        });
            }
            //更新状态
            Map<String, String>  paramsInner =  DTSUtils.getSignature();
            paramsInner.put(FILE_NAME, fileVideo.getFileName());
            List<FileStatus> listFileStatus = getList(Status_INFO_URL, FileStatus.class, paramsInner);
            if(CollectionUtils.isNotEmpty(listFileStatus)){
                fileVideo.setStatus(listFileStatus.get(0).getStatus());

                listDeviceLedger.stream().filter(e->targetDeviceNum.equals(e.getDeviceNum()))
                        .findFirst()
                        .ifPresent(deviceLedger -> {
                            deviceLedger.setMonitorStatus(listFileStatus.get(0).getStatus());
                            deviceLedgerService.updateById(deviceLedger);
                        });
            }
        });
        boolean flagFileVideo = fileVideoService.saveBatch(listFileVideo);
        if (!flagFileVideo) {
            log.error("同步测漏仪数据-音频信息保存失败");
            return;
        }
        //迭代根据音频文件表的文件名 查询状态及频谱数据
        //插入频谱图表
        for (FileVideo fileVideo : listFileVideo){
            String fileName = fileVideo.getFileName();
            if(StringUtils.isBlank(fileName)){
                continue;
            }
            Map<String, String>  paramsInner =  DTSUtils.getSignature();
            paramsInner.put(FILE_NAME, fileName);
            JSONArray listVideoSpectrum = getDataString(WAV_FILE_SPECTRUM_URL, paramsInner);
            if(CollectionUtils.isNotEmpty(listVideoSpectrum)){
                VideoSpectrum videoSpectrum = new VideoSpectrum();
                videoSpectrum.setFileVideoId(fileVideo.getId());
                videoSpectrum.setCreateBy(DEFAULT_USER_NAME);
                videoSpectrum.setUpdateBy(DEFAULT_USER_NAME);
                videoSpectrum.setCreateTime(currentDate);
                videoSpectrum.setUpdateTime(currentDate);
                videoSpectrum.setDetailData(listVideoSpectrum.toJSONString());
                boolean flagVideoSpectrum = videoSpectrumService.save(videoSpectrum);
                if (!flagVideoSpectrum) {
                    log.error("同步测漏仪数据-频谱信息保存失败");
                }
            }
            //TODO  音频文件下载单独一个任务  先不拆 看厂商服务器是否满足 后续看情况拆另一个定时任务
            // 下载音频文件
            paramsInner =  DTSUtils.getSignature();
            paramsInner.put(FILE_NAME, fileName);
            MultipartFile multipartFile = getMultipartFile(DOWNLOAD_WAV_FILE_URL, paramsInner);
            if(multipartFile.isEmpty()){
                log.error("同步测漏仪数据-音频文件转化失败");
                continue;
            }
            String pathFileName = FileUploadUtils.uploadMinio(multipartFile);
            fileVideo.setFileUrl(pathFileName);
            boolean flagFileVideoU = fileVideoService.updateById(fileVideo);
            if (!flagFileVideoU) {
                log.error("同步测漏仪数据-音频文件更新失败");
            }
        }

    }




        public static MultipartFile convert(String data, String filename, String contentType) throws Exception {
            byte[] bytes = data.getBytes(Charset.forName("ISO-8859-1"));
            // 将字节数组包装为InputStream
            // FileItem fileItem;
            File tempDir = Files.createTempDirectory("dtsTaskUpload-").toFile();
            File tempFile = new File(tempDir, filename);
            // File tempFile = new File("D:\\Desktop\\德高文档\\testtest.wav");
            if(!tempFile.exists()){
               tempFile.createNewFile();
            }
            try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
                // 创建临时文件存储数据，注意这里使用了系统临时目录
                // tempDir = Files.createTempDirectory("dtsTaskUpload-").toFile();
                // fileItem = new DiskFileItem("file", contentType, false, filename, bytes.length, tempDir);

                // 写入临时文件
                OutputStream os = null;
                try {
                    // os = fileItem.getOutputStream();
                    os = new FileOutputStream(tempFile);
                    int bytesRead;
                    byte[] buffer = new byte[1024];
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                    os.flush();
                    os.close();
                    inputStream.close();
                } catch (IOException e) {
                    throw new Exception("文件写入异常: " + e.getMessage(), e);
                } finally {
                    if (os != null) {
                        try {
                            os.close();
                        } catch (IOException e) {
                            // 忽略关闭异常
                        }
                    }
                }
            }


            FileInputStream fileInputStream = new FileInputStream(tempFile);
            // multipartFile = new MultipartFileDto(filePath, filePath, ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
            // IOUtils.copy(fileInputStream, tempFile);
            // return new CommonsMultipartFile(tempDir);
            return new MultipartFileDto2(tempFile.getPath(), filename
                    , "audio-wav", fileInputStream);
        }


    // public static MultipartFile fileToMultipartFile(File file) {
    //     MultipartFile multipartFile = cn.hutool.core.io.FileUtil.to(file);
    //     return multipartFile;
    // }

    public static void main(String[] args) {
        Map<String, String>  paramsInner =  DTSUtils.getSignature();
        paramsInner.put(FILE_NAME, "24120838-250630100710.wav");

        String buildUrl = UrlBuilder.create()
                .setScheme("http") //http方式
                .setHost("39.105.151.103") //ip
                .setPort(8080) //端口
                .addPath("/wam/api/").addPath("v1/downloadWavFile")
                .addQuery(FILE_NAME, paramsInner.get(FILE_NAME))

                .addQuery("timestamp", paramsInner.get("timestamp"))
                .addQuery("signature", paramsInner.get("signature"))
                .addQuery("accessKeyId", paramsInner.get("accessKeyId"))
                .setCharset(Charset.forName(CharsetUtil.UTF_8)) //这里需要对传的2021-10-18 10:10:01 UrlEncode编码
                .build();
        long file = HttpUtil.downloadFile(buildUrl, "d:/test02.wav"); //下载并创建d:/test02.mp4


    }

    /**
     *   TODO  【任务管理】报警状态更改定时任务 以任务时间查询
     * @throws Exception
     */
    public void updateTaskStatus() throws Exception {
        System.out.println("================start task  status============================");
        //TODO   拉取所有的设备信息   将日期填充进 表示为今天的设备信息 入台账表
        //获取今天的日期  减1得到状态的日期
        // 任务刷选 条件  传入的日期  在任务的开始- 结束时间内
        // 刷选出所有的符合挂接设备的设备记录
        //如果有一条预警的则为 预警
        //        疑似的则为 疑似
        //其他则为正常
        Map<String, Object> params = new HashMap<>();
        params.put("cronTimeStart", DateUtils.getBeforeYesterdayStart());
        params.put("cronTimeEnd", DateUtils.getBeforeYesterdayEnd());
        List<TaskManagement>  taskManagementListDeal = taskManagementService.selectTaskManagementListByMap(params);
        if(CollectionUtils.isEmpty(taskManagementListDeal)){
            return;
        }
        Map<String, Object> paramsInner = null;
        for (TaskManagement taskManagementDeal : taskManagementListDeal) {
              paramsInner = new HashMap<>();
              paramsInner.put("id", taskManagementDeal.getId());
              List<DeviceLedger> deviceLedgerList  = deviceLedgerService.listDeviceLedgerByMap(paramsInner) ;
              if(CollectionUtils.isEmpty(deviceLedgerList)){
                  continue;
              }
              long yjCount = deviceLedgerList.stream().filter(deviceLedger ->
                     deviceLedger.getMonitorStatus().equals(TASK_STATUS_WARNING_CN)).count();
              if(yjCount > 0L){
                  if(taskManagementDeal.getTaskStatus().equals(TASK_STATUS_WARNING_VALUE)){
                     continue;
                  }else{
                      taskManagementDeal.setTaskStatus(TASK_STATUS_WARNING_VALUE);
                      taskManagementDeal.setUpdateTime(new Date());
                      taskManagementService.updateByIdNew(taskManagementDeal);
                  }
              }

            long ysCount = deviceLedgerList.stream().filter(deviceLedger ->
                    deviceLedger.getMonitorStatus().equals(TASK_STATUS_SUSPECTED_CN)).count();
            if(ysCount > 0L){
                if(taskManagementDeal.getTaskStatus().equals(TASK_STATUS_SUSPECTED_VALUE)){
                    continue;
                }else{
                    taskManagementDeal.setTaskStatus(TASK_STATUS_SUSPECTED_VALUE);
                    taskManagementDeal.setUpdateTime(new Date());
                    taskManagementService.updateByIdNew(taskManagementDeal);
                }
            }
        }


    }


}
